package com.aiti.lulian.server;



import com.aiti.lulian.entity.MsgInbox;
import com.aiti.lulian.service.MsgInboxService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint("/webSocket/{userId}")
@Component
@Slf4j
public class WebSocketServer {

    private static AtomicInteger onlineNum = new AtomicInteger(0);
    private static Map<String, Session> sessionPools = new ConcurrentHashMap<>();


    private static MsgInboxService msgInboxService;

    @Autowired
    public void setMsgInboxService(MsgInboxService msgInboxService) {
        WebSocketServer.msgInboxService = msgInboxService;
    }




    public void sendMessage(Session session, String message) throws IOException {
        if (session != null) {
            synchronized (session) {
                log.info("发送数据：" + message);
                session.getBasicRemote().sendText(message);
            }
        }
    }

    public void sendInfo(String userId, String message) {
        Session session = sessionPools.get(userId);
        try {
            sendMessage(session, message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void broadcast(String message) {
        sessionPools.values().forEach(session -> {
            try {
                sendMessage(session, message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        sessionPools.put(userId, session);
        onlineNum.incrementAndGet();
        log.info(userId + " 加入 WebSocket！当前人数为 " + onlineNum);

        // 加载历史消息
        loadHistoryMessages(userId);

        // 广播上线消息
//        Message msg = new Message();
//        msg.setDate(new Date());
//        msg.setTo("0");
//        msg.setText(userName);
//        broadcast(JSON.toJSONString(msg, true));
    }

    @OnClose
    public void onClose(@PathParam(value = "userId") String userId) {
        sessionPools.remove(userId);
        onlineNum.decrementAndGet();
        log.info(userId + " 断开 WebSocket 连接！当前人数为 " + onlineNum);

        // 广播下线消息
//        Message msg = new Message();
//        msg.setDate(LocalDateTime.now());
//        msg.setTo("-2");
//        msg.setText(userName);
//        broadcast(JSON.toJSONString(msg, true));
    }

    @OnMessage
    public void onMessage(String message) throws IOException {
        log.info("server get " + message);
        MsgInbox msg = JSON.parseObject(message, MsgInbox.class);
        msg.setBaseCreateTime(new Date());
        //保存消息到数据库
        msgInboxService.save(msg);

        sendInfo(msg.getReceiverId(), JSON.toJSONString(msg, true));
    }

    @OnError
    public void onError(Session session, Throwable throwable) throws IOException {
        if (session.isOpen()) {
            session.close();
        }
    }

    private void loadHistoryMessages(String userId) {
        LambdaQueryWrapper<MsgInbox> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MsgInbox::getReceiverId, userId).orderByAsc(MsgInbox::getStatus).orderByDesc(MsgInbox::getBaseCreateTime);
        List<MsgInbox> messages = msgInboxService.list(wrapper);
        if(!CollectionUtils.isEmpty(messages)){
            messages.forEach(msg -> {
                try {
                    sendMessage(sessionPools.get(userId), JSON.toJSONString(msg, true));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }

    }


    public void saveAndSendMessage(String message) throws IOException {
        log.info("server get " + message);
        MsgInbox msg = JSON.parseObject(message, MsgInbox.class);
        msg.setBaseCreateTime(new Date());
        //保存消息到数据库
        msgInboxService.save(msg);

        sendInfo(msg.getReceiverId(), JSON.toJSONString(msg, true));
    }

    public static AtomicInteger getOnlineNumber() {
        return onlineNum;
    }

    public static Map<String, Session> getSessionPools() {
        return sessionPools;
    }
}
